package com.trytech.mongoocrawler.server;

import com.trytech.mongoocrawler.server.common.enums.LifeCycle;
import com.trytech.mongoocrawler.server.common.queue.DisruptorContext;
import com.trytech.mongoocrawler.server.transport.UrlManager;
import com.trytech.mongoocrawler.server.transport.UrlParserPair;
import com.trytech.mongoocrawler.server.transport.http.CrawlerHttpRequest;
import com.trytech.mongoocrawler.server.transport.http.factory.CrawlerHttpReqFactory;
import com.trytech.mongoocrawler.server.xml.CrawlerXmlConfigBean;

/**
 * 一次爬取会话
 * 会话的生命周期包括：
 *      INITIALIZED=0-初始化
 *      RUNNING=1-已运行
 *      PAUSED=2-暂停
 *      DESTORYED=3-已销毁
 */
public final class LocalCrawlerSession extends CrawlerSession implements Runnable {

    //父容器
    private CrawlerContext container;
    //运行模式
    private int runmode;


    /***
     * 构造函数
     * @param container 父容器
     */
    public LocalCrawlerSession(CrawlerContext container, CrawlerXmlConfigBean crawlerXmlConfigBean, UrlParserPair[] urlParserPairs){
        this.container = container;
        lifeCycle = LifeCycle.INITIALIZED;
        if(urlParserPairs != null) {
            this.urlManager.pushUrls(urlParserPairs);
        }
        this.sessionConfig = crawlerXmlConfigBean;
        this.runmode = crawlerXmlConfigBean.getRunmode();
        disruptorContext = DisruptorContext.getInstance(this);
    }
    public LocalCrawlerSession(CrawlerContext container, CrawlerXmlConfigBean crawlerXmlConfigBean , UrlParserPair[] urlParserPairs, UrlManager urlManager){
        this.container = container;
        lifeCycle = LifeCycle.INITIALIZED;
        this.urlManager = urlManager;
        if(urlParserPairs != null) {
            this.urlManager.pushUrls(urlParserPairs);
        }
        this.sessionConfig = crawlerXmlConfigBean;
        this.runmode = crawlerXmlConfigBean.getRunmode();
        disruptorContext = DisruptorContext.getInstance(this);
    }

    @Override
    public void run() {
        try {
            RUN_MODE runMode = RUN_MODE.parseMode(runmode);
            //启动disruptor
            if (!disruptorContext.isStarted()) {
                disruptorContext.start();
            }
            //如果该会话已启动或已销毁均不能再启动
            if (lifeCycle != LifeCycle.DESTORYED && lifeCycle != LifeCycle.RUNNING) {
                while (true) {
                    try {
                        if (lifeCycle == LifeCycle.DESTORYED) {
                            break;
                        }
                        if (urlManager.isQueueEmpty()) {
                            lifeCycle = LifeCycle.FREE;
                        }
                        UrlParserPair urlParserPair = urlManager.fetchUrl();
                        lifeCycle = LifeCycle.RUNNING;
                        if (urlParserPair != null) {
                            System.out.println("正在爬取url:" + urlParserPair.getUrl().toString());
                            /*********************************************************************
                             * http request工厂需要提供封装参数和header以及cookie的接口
                             ********************************************************************/
                            CrawlerHttpRequest request = CrawlerHttpReqFactory.getRequest(urlParserPair.toURL(), urlParserPair.getHtmlParser());
                            request.setSessionId(sessionId);
                            submitTask(request);
                            Thread.currentThread().sleep(1000);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            lifeCycle = LifeCycle.DESTORYED;
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void pause(){
        lifeCycle = LifeCycle.PAUSED;
    }

    public void destory(){
        lifeCycle = LifeCycle.DESTORYED;
        container.removeSession(sessionId);
        container.checkStatus();
        container = null;
    }

    public boolean isPaused(){
        return lifeCycle == LifeCycle.PAUSED;
    }

    public boolean isDestoryed(){
        return lifeCycle == LifeCycle.DESTORYED;
    }


    public int getRunmode() {
        return runmode;
    }

    public void setRunmode(int runmode) {
        this.runmode = runmode;
    }

    public void ifNeedClose() {
        if(isPaused()){
            container.interruptSession(sessionId);
        }
    }

    private enum RUN_MODE{
        NON_STOP(1), STATUS_MONITOR(2),RUN_UNTIL_EMPTY(3);
        private int mode;
        private RUN_MODE(int mode){
            this.mode = mode;
        }

        public static RUN_MODE parseMode(int mode){
            switch (mode){
                case 3:
                    return RUN_UNTIL_EMPTY;
                case 2:
                    return STATUS_MONITOR;
                default:
                    return NON_STOP;
            }
        }

        public int getMode(){
            return mode;
        }
    }
}
